import { coTurnConfig } from "./coturn";
import { MessageType, type MessageData } from "./MessageData";
import type { SignalingClient } from "./SignalingClient";

export class WebRtc {
    private peers: { [key: string]: RTCPeerConnection } = {};
    constructor(
        private localStream: MediaStream,
        private signalingClient: SignalingClient,
        private onRemoteStream: (stream: MediaStream, id: string) => void
    ) {
        this.signalingClient.removeHand = (peerId) => {
            console.log("删除", peerId,this.peers);
            //删除peers
            const pc = this.peers[peerId]
            if (pc) {
                pc.close();
                pc.onicecandidate = null;
                pc.ontrack = null;
            }
            delete this.peers[peerId];

        }
    }
    stop(localUserId:string){
        this.localStream.getTracks().forEach(e=>{
            e.stop();
        })
        this.signalingClient.send({ type: MessageType.bye })

    }
    createPeerConnection = (peerId: string): RTCPeerConnection => {
        if (this.peers[peerId]) return this.peers[peerId];
        const peer = new RTCPeerConnection(coTurnConfig.defualtConfig);
        peer.ontrack = (event) => {
            this.onRemoteStream(event.streams[0], peerId);
        }
        peer.onicecandidate = (event) => event.candidate && this.signalingClient.send({ type: MessageType.ice, to: peerId, data: event.candidate });
        peer.onnegotiationneeded = async () => {
            const offer = await peer.createOffer();
            await peer.setLocalDescription(offer);
            this.signalingClient.send({ data: offer, to: peerId, type: MessageType.offer });
        };
        this.localStream.getTracks().forEach(track => {
            peer.addTrack(track, this.localStream);
        })
        this.peers[peerId] = peer;
        return peer;
    }
    async handleOffer(message: MessageData): Promise<void> {
        const { type, sender, data } = message;
        const peer = this.peers[sender!] || this.createPeerConnection(sender!);
        await peer.setRemoteDescription(new RTCSessionDescription(data));
        if (type === MessageType.offer) {
            const answer = await peer.createAnswer();
            await peer.setLocalDescription(answer);
            this.signalingClient.send({
                type: MessageType.answer,
                to: message.sender,
                data: answer,
            });
        }
    }
    async handleAnswer(message: MessageData): Promise<void> {
        const { sender, data } = message;
        const { sdp } = data;
        if (this.peers[sender!]) await this.peers[sender!].setRemoteDescription({ type: "answer", sdp });
    }
    async handleICE(message: MessageData): Promise<void> {
        const peer = this.peers[message.sender!];
        if (peer) {
            await peer.addIceCandidate(new RTCIceCandidate(message.data));
        }
    }
}